﻿using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace Core
{
    public class Config<KeyType>
    {
        public KeyType id;
    }

    public class ConfigExcel<ConfigType, KeyType> : ScriptableObject where ConfigType : Config<KeyType>
    {
        public ConfigType[] configs = new ConfigType[0];

        [NonSerialized]
        public Dictionary<KeyType, ConfigType> maps = new Dictionary<KeyType, ConfigType>();
        
        [NonSerialized]
        internal string filePath;

        internal void Init(string assetFilePath = "")
        {
            if (!string.IsNullOrEmpty(assetFilePath))
                filePath = assetFilePath;
            else
                filePath = GetDefaultPath();

            var asset = new LoadAsset<UnityEngine.Object>(filePath).Publish().asset as ConfigExcel<ConfigType, KeyType>;
            if (asset == null)
            {
                Debug.LogError($"can not get excel data: {filePath}");
                return;
            }

            try
            {
                configs = new ConfigType[asset.configs.Length];
                Array.Copy(asset.configs, configs, asset.configs.Length);
                foreach (var row in asset.configs)
                    maps[row.id] = row;

                new UnloadAsset(filePath).Publish();
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }

            OnInit();
        }

        public ConfigType GetID(KeyType id)
        {
            ConfigType row;
            if (maps.TryGetValue(id, out row))
                return row;

            Debug.LogError($"找不到对应的ID，容错返回第一个， id:{id}, path:{filePath}");
            if (maps.Count > 0)
                return maps.First().Value;

            return null;
        }

        public bool IsContainID(KeyType id)
        {
            return maps.ContainsKey(id);
        }

        protected virtual void OnInit() { }

        internal string GetDefaultPath()
        {
            var typeName = GetType().ToString();
            var index = typeName.LastIndexOf('.');

            var fileName = string.Empty;
            if (index > 0)
                fileName = typeName.Substring(index);
            else
                fileName = typeName;

            return $"{GameConst.EXCEL_PATH}/{fileName}/{fileName}.asset";
        }
    }

    public class ConfigExcel<ExcelType, ConfigType, KeyType> : ConfigExcel<ConfigType, KeyType>
        where ExcelType : ConfigExcel<ConfigType, KeyType>
        where ConfigType : Config<KeyType>
    {
        private static ExcelType m_ins;
        public static ExcelType Ins
        {
            get
            {
                if (m_ins == null)
                    InitInstance();

                return m_ins;
            }
        }

        public static void Reload(string assetPath)
        {
            Clear();
            InitInstance(assetPath);
        }

        public static void Clear()
        {
            m_ins = null;
        }

        private static void InitInstance(string assetPath = "")
        {
            if (m_ins == null)
            {
                m_ins = ScriptableObject.CreateInstance<ExcelType>();
                m_ins.Init(assetPath);
            }
        }
    }
}
